﻿using System;
using System.Linq;
using System.Windows.Forms;
using DBCodeBuilder.Core.Classes;
using DBCodeBuilder.Core.Enum;
using DBCodeBuilder.Core.Models;

namespace DBCodeBuilder.UI
{
    public partial class Map_Props : HComp
    {
        public event EventHandler OnSave;
        private TableModel Model;
        private DbRelationship Relationship;
        private bool isView;
        private int keyFields;

        public new bool Visible
        {
            get { return splitContainer1.Visible; }
            set { splitContainer1.Visible = value; }
        }

        public Map_Props()
        {
            InitializeComponent();
            btnAddKeyField.Image = Properties.Resources.add_plus2_24x24;

            if (IsDesignMode)
                return;

            cmbRelType.Items.AddRange(Enum.GetNames(typeof (DbRelationshipType)));
            cmbRelType.SelectedIndex = 0;

            cmbCascStyleDirect.Items.AddRange(Enum.GetNames(typeof (DbCascadeStyle)));
            cmbCascStyleDirect.SelectedIndex = 0;

            cmbCascStyleInverse.Items.AddRange(Enum.GetNames(typeof (DbCascadeStyle)));
            cmbCascStyleInverse.SelectedIndex = 0;
        }

        public void Init(TableModel model)
        {
            lblTab.Text = String.Format("{0}", model.Name);

            Model = model;
            Relationship = null;
            txtClassName.Text = model.UserMapping.ClassName;
            txtCollectionName.Text = model.UserMapping.SetName;

            isView = model.ObjectType == DbObjectType.View;
            if (isView)
                LoadPanelFlow();

            AdjustDisplay();
        }

        public void Init(DbRelationship rel)
        {
            lblRel.Text = String.Format("{0} ----- {1}", rel.OriginalTable, rel.RefTable);

            Relationship = rel;
            Model = null;

            cmbRelType.SelectedItem = cmbRelType.Items[cmbRelType.Items.IndexOf(rel.RelType.ToString())];
            cmbCascStyleDirect.SelectedItem = cmbCascStyleDirect.Items[cmbCascStyleDirect.Items.IndexOf(rel.CascadeStyleDirect.ToString())];
            cmbCascStyleInverse.SelectedItem = cmbCascStyleDirect.Items[cmbCascStyleDirect.Items.IndexOf(rel.CascadeStyleInverse.ToString())];
            chkGenerate.Checked = rel.Generate;
            chkGenInverse.Checked = rel.GenerateInverse;
            chkLazyDirect.Checked = rel.LazyLoadingDirect;
            chkLazyInverse.Checked = rel.LazyLoadingInverse;
            chkNullableDirect.Checked = rel.NullableDirect;

            AdjustDisplay();
        }

        private void AdjustDisplay()
        {
            lblUpdInfo.Visible = false;
            lblRelInfo.Visible = false;

            Visible = true;

            if (Model == null)
            {
                splitContainer1.Panel1Collapsed = true;
                splitContainer1.Panel2Collapsed = false;
            }
            else
            {
                pnlView.Visible = isView;
                splitContainer1.Panel1Collapsed = false;
                splitContainer1.Panel2Collapsed = true;
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            Model.UserMapping.ClassName = String.IsNullOrEmpty(txtClassName.Text) ? Model.UserMapping.ClassName : txtClassName.Text;
            Model.UserMapping.SetName = String.IsNullOrEmpty(txtCollectionName.Text) ? Model.UserMapping.SetName : txtCollectionName.Text;
            {
                string keys = "";
                for (int i = 0; i < keyFields; i++)
                {
                    var cmb = pnlFlow.Controls.Find("cmbKeyField" + (i + 1), true).Single() as ComboBox;
                    if (keys.Contains(cmb.SelectedItem + "|"))
                    {
                        MessageBox.Show("The same key has been added multiple times.");
                        return;
                    }
                    keys += cmb.SelectedItem + "|";
                }
                keys = keys.TrimEnd('|');
                Model.ForcedPrimaryKey = keys;
            }

            lblUpdInfo.Visible = true;

            if (OnSave != null)
                OnSave(Model, null);

            LoadPanelFlow();
        }

        private void LoadPanelFlow()
        {
            //Ripulisce il pannello dai controlli inutili
            var controls = pnlFlow.Controls.Cast<Control>().ToList();
            foreach (Control ctr in controls)
            {
                if (!ctr.In(btnAddKeyField, cmbKeyField1))
                    pnlFlow.Controls.Remove(ctr);
            }

            //Ricarica tutti i controlli
            var fields = Model.ForcedPrimaryKey.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            keyFields = !fields.Any() ? 1 : fields.Count();

            cmbKeyField1.Items.Clear();
            cmbKeyField1.Items.Add("");
            cmbKeyField1.Items.AddRange(Model.MetaData.Columns.Select(t => t.Name).ToArray());
            if (!fields.Any())
                cmbKeyField1.SelectedItem = "";
            else
                cmbKeyField1.SelectedItem = fields[0];

            for (int i = 1; i < keyFields; i++)
                AddFieldComboBox(fields[i], false, (i + 1));
            btnAddKeyField.SendToBack();
        }

        private void btnRelInfoSave_Click(object sender, EventArgs e)
        {
            Relationship.RelType = (DbRelationshipType) Enum.Parse(typeof (DbRelationshipType), cmbRelType.SelectedItem.ToString());
            Relationship.CascadeStyleDirect = (DbCascadeStyle) Enum.Parse(typeof (DbCascadeStyle), cmbCascStyleDirect.SelectedItem.ToString());
            Relationship.CascadeStyleInverse = (DbCascadeStyle) Enum.Parse(typeof (DbCascadeStyle), cmbCascStyleInverse.SelectedItem.ToString());
            Relationship.Generate = chkGenerate.Checked;
            Relationship.GenerateInverse = chkGenInverse.Checked;
            Relationship.LazyLoadingDirect = chkLazyDirect.Checked;
            Relationship.LazyLoadingInverse = chkLazyInverse.Checked;
            Relationship.NullableDirect = chkNullableDirect.Checked;

            lblRelInfo.Visible = true;

            if (OnSave != null)
                OnSave(Relationship, null);
        }

        private void txtentityProp_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                btnSave_Click(null, null);
        }

        private void chkGenInverse_CheckedChanged(object sender, EventArgs e)
        {
            grpInverse.Enabled = chkGenInverse.Checked;
        }

        private void chkGenerate_CheckedChanged(object sender, EventArgs e)
        {
            if (!chkGenerate.Checked)
            {
                grpDirect.Enabled = false;
                grpInverse.Enabled = false;
                cmbRelType.Enabled = false;
                chkGenInverse.Enabled = false;
            }
            else
            {
                grpDirect.Enabled = true;
                cmbRelType.Enabled = true;
                chkGenInverse.Enabled = true;
                chkGenInverse_CheckedChanged(null, null);
            }
        }

        private void cmbRelType_SelectedIndexChanged(object sender, EventArgs e)
        {
            var selectedRelation =
                (DbRelationshipType) Enum.Parse(typeof (DbRelationshipType), cmbRelType.SelectedItem.ToString());
            if (selectedRelation == DbRelationshipType.OneToOne)
            {
                chkNullableDirect.Checked = false;
                chkNullableDirect.Visible = false;
            }
            else
                chkNullableDirect.Visible = true;
        }

        private void AddFieldComboBox(string value, bool SendToBackAddButton = true, int? forcedIndex = null)
        {
            ComboBox cmb = new ComboBox
            {
                Name = "cmbKeyField" + (forcedIndex.HasValue ? forcedIndex.Value : keyFields),
                DropDownStyle = ComboBoxStyle.DropDownList,
                Margin = new Padding(0, 0, 3, 0)
            };

            cmb.Items.Add("");
            cmb.Items.AddRange(Model.MetaData.Columns.Select(t => t.Name).ToArray());
            cmb.SelectedItem = value;
            pnlFlow.Controls.Add(cmb);
            if (SendToBackAddButton)
                btnAddKeyField.SendToBack();
        }

        private void btnAddKeyField_Click(object sender, EventArgs e)
        {
            keyFields++;
            AddFieldComboBox("");
        }
    }
}